﻿using ShiQuan.RemoteHelper;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Xml;

namespace ShiQuan.Remoting.Helper
{
    /// <summary>
    /// 服务器辅助对象
    /// </summary>
    public class ServerHelper : IDisposable
    {
        /// <summary>
        /// 远程服务器
        /// </summary>
        private Socket _RemoteSocket = null;
        /// <summary>
        /// 获取远程服务器
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public Socket GetRemoteSocket(out string msg)
        {
            msg = string.Empty;
            //if(this._RemoteSocket != null)
            //{
            //    return this._RemoteSocket;
            //}
            if (System.IO.File.Exists(AppConfig.FileName) == false)
                AppConfig.InitConfig();

            //设定服务器IP地址 
            IPAddress ip = IPAddress.Parse(AppConfig.Server); /*12.0.0.1*/
            try
            {
                int port = 16888;
                int.TryParse(AppConfig.Port, out port);
                this._RemoteSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                this._RemoteSocket.SendTimeout = 60 * 1000;
                this._RemoteSocket.ReceiveTimeout = 60 * 1000;//60秒
                this._RemoteSocket.Connect(new IPEndPoint(ip, port)); //配置服务器IP与端口 
                Logger.Info("连接服务器成功");
                return this._RemoteSocket;
            }
            catch (Exception ex)
            {
                Logger.Error("连接服务器失败", ex);
                msg = "连接服务器失败";
                return null;
            }
        }
        /// <summary>
        /// 注册信息
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool Regist(out string msg)
        {
            msg = string.Empty;
            byte[] bytes = new byte[1024 * 1024];
            //通过 clientSocket 发送数据
            string request = string.Empty; 
            try
            {
                LocalInfo loaclInfo = LocalHelper.GetLocalInfo();
                if (string.IsNullOrEmpty(AppConfig.Password))
                    loaclInfo.Password = new Random().Next(100000, 999999).ToString();//"123456";
                else
                    loaclInfo.Password = AppConfig.Password;
                loaclInfo.Port = AppConfig.Port;

                var jsonData = JsonHelper.ToJson(loaclInfo);
                //var sendInfo = this.GetActionInfo("Regist", );
                request = this.Send("Regist", jsonData, out msg);
                LocalHelper.Password = loaclInfo.Password;
            }
            catch(Exception ex)
            {
                Logger.Error("发送信息异常", ex);
                msg = "发送信息异常";
                return false;
            }
            try
            {
                var result = this.GetResult(request);
                if(result.Code != "0")
                {
                    msg = result.Message;
                    return false;
                }
                var localInfo = JsonHelper.GetObject<LocalInfo>(result.Result);
                LocalHelper.KeyValue = localInfo.KeyValue;
                msg = "注册成功";
                return true;
            }
            catch (Exception ex)
            {
                Logger.Error("解释信息异常", ex);
                msg = "解释信息异常";
                return false;
            }
        }

        /// <summary>
        /// 注册信息
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public LocalInfo GetRemoteInfo(string remoteId,out string msg)
        {
            msg = string.Empty;
            if (this.GetRemoteSocket(out msg) == null)
                return null;
            
            //通过 clientSocket 发送数据
            string result = string.Empty;
            try
            {
                RequestRemoteInfo request = new RequestRemoteInfo();
                request.RequestId = LocalHelper.KeyValue;
                request.RemoteId = remoteId;

                var jsonData = JsonHelper.ToJson(request);
                //var sendInfo = this.GetActionInfo("GetRemoteInfo", jsonData);
                result = this.Send("GetRemoteInfo", jsonData, out msg);
            }
            catch (Exception ex)
            {
                Logger.Error("接收信息异常", ex);
                msg = "接收信息异常";
                return null;
            }
            try
            {
                var requestResult = this.GetResult(result);
                if (requestResult.Code != "0")
                {
                    msg = requestResult.Message;
                    return null;
                }
                return JsonHelper.GetObject<LocalInfo>(requestResult.Result);
            }
            catch (Exception ex)
            {
                Logger.Error("解释信息异常", ex);
                msg = "解释信息异常";
                return null;
            }
        }

        /// <summary>
        /// 注册信息
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool SendFile(string fileName, out string msg)
        {
            msg = string.Empty;
            string result = string.Empty;
            try
            {
                byte[] fileContent = System.IO.File.ReadAllBytes(fileName);

                FileInfo fileInfo = new FileInfo(fileName);
                RequestHeader header = new RequestHeader();
                header.Action = "SendFile";
                header.FileName = fileInfo.Name;
                header.ContentLength = fileContent.Length;

                result = this.Send(header, fileContent, out msg);
            }
            catch (Exception ex)
            {
                Logger.Error("发送接收信息异常", ex);
                msg = "发送接收信息异常";
                return false;
            }
            try
            {
                var requestResult = this.GetResult(result);
                if (requestResult.Code != "0")
                {
                    msg = requestResult.Message;
                    return false;
                }
                return true;
            }
            catch (Exception ex)
            {
                Logger.Error("解释信息异常", ex);
                msg = "解释信息异常";
                return false;
            }
        }

        /// <summary>
        /// 注册信息
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public string Send(string action, string jsonData, out string msg)
        {
            msg = string.Empty;
            RequestHeader header = new RequestHeader();
            header.Action = action;
            return this.Send(header, jsonData, out msg);
        }
        /// <summary>
        /// 注册信息
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public string Send(RequestHeader header,string jsonData, out string msg)
        {
            msg = string.Empty;
            byte[] data = System.Text.Encoding.UTF8.GetBytes(jsonData);
            return this.Send(header, data, out msg);
        }

        /// <summary>
        /// 注册信息
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public string Send(RequestHeader header, byte[] data, out string msg)
        {
            msg = string.Empty;
            if (this.GetRemoteSocket(out msg) == null)
                return string.Empty;

            //通过 clientSocket 发送数据
            string result = string.Empty;
            try
            {
                header.ContentLength = data.Length;
                StringBuilder content = new StringBuilder();
                foreach (var item in header.GetFieldValue())
                {
                    content.AppendLine(item.Key + ":" + item.Value);
                }
                content.AppendLine();
                //var sendInfo = this.GetActionInfo("SendFile", JsonHelper.ToJson(sendFileInfo));
                Logger.Info("向服务器发送消息：" + content.ToString());
                this._RemoteSocket.Send(Encoding.UTF8.GetBytes(content.ToString()));
                //发送内容
                this._RemoteSocket.Send(data);

                //通过clientSocket接收数据 
                byte[] bytes = new byte[1024 * 1024];
                int receiveLength = _RemoteSocket.Receive(bytes);
                result = Encoding.UTF8.GetString(bytes, 0, receiveLength);
                Logger.Info("接收服务器消息：" + result);
                return result;
            }
            catch (Exception ex)
            {
                Logger.Error("接收信息异常", ex);
                _RemoteSocket.Shutdown(SocketShutdown.Both);
                _RemoteSocket.Close();
                this._RemoteSocket = null;
                msg = "接收信息异常";
                return string.Empty;
            }
        }
        /// <summary>
        /// 注册信息
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public bool Close()
        {
            if (this._RemoteSocket == null)
                return true;
            try
            {
                _RemoteSocket.Shutdown(SocketShutdown.Both);
                _RemoteSocket.Close();
                Logger.Info("关闭服务器成功");
                return true;
            }
            catch (Exception ex)
            {
                Logger.Error("关闭服务器失败", ex);
                return false;
            }
        }

        /// <summary>
        /// 获取注册信息
        /// </summary>
        /// <param name="loaclInfo"></param>
        /// <returns></returns>
        public string GetRegistInfo(LocalInfo loaclInfo)
        {
            XmlDocument doc = new XmlDocument();
            doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", "yes"));
            XmlElement root = doc.CreateElement("root");
            XmlNode node = doc.CreateElement("action");
            node.InnerText = "Regist";
            root.AppendChild(node);

            XmlNode data = doc.CreateElement("data");
            foreach (var item in loaclInfo.GetFieldValue())
            {
                node = doc.CreateElement(item.Key);
                node.InnerText = item.Value;
                data.AppendChild(node);
            }
            root.AppendChild(data);
            doc.AppendChild(root);
            return doc.OuterXml;
        }
        /// <summary>
        /// 获取注册信息
        /// </summary>
        /// <param name="loaclInfo"></param>
        /// <returns></returns>
        public string GetActionInfo(string actionName,string data)
        {
            
            XmlDocument doc = new XmlDocument();
            doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", "yes"));
            XmlElement root = doc.CreateElement("root");
            XmlNode action = doc.CreateElement("action");
            action.InnerText = actionName;
            root.AppendChild(action);

            XmlNode node = doc.CreateElement("data");
            node.InnerText = data;
            root.AppendChild(node);

            doc.AppendChild(root);
            return doc.OuterXml;
        }

        /// <summary>
        /// 获取注册信息
        /// </summary>
        /// <param name="loaclInfo"></param>
        /// <returns></returns>
        public string GetActionXml(string actionName, string data)
        {
            XmlDocument doc = new XmlDocument();
            doc.AppendChild(doc.CreateXmlDeclaration("1.0", "utf-8", "yes"));
            XmlElement root = doc.CreateElement("root");
            XmlNode action = doc.CreateElement("action");
            action.InnerText = actionName;
            root.AppendChild(action);

            XmlNode node = doc.CreateElement("data");
            node.InnerText = data;
            root.AppendChild(node);

            doc.AppendChild(root);
            return doc.OuterXml;
        }
        /// <summary>
        /// 获取结果
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public RequestResult GetResult(string request)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(request);
            RequestResult result = new RequestResult();
            foreach (XmlElement item in doc.DocumentElement.ChildNodes)
            {
                result.Set(item.Name, item.InnerText);
            }
            return result;
        }
        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            this.Close();
        }
    }
}
